Not applicable.
The present invention relates generally to methods for testing memory devices. More particularly, the present invention relates to methods for detecting faults in dual port and single port content addressable static memories.
Fast, efficient testing is an important step in manufacturing memory chips, and the price paid for recent advances in semiconductor technology has been a lengthier and more complicated testing process. A common feature of some memory devices is the capability to quickly search for patterns stored among groups of memory cells. These types of memory devices are called content addressable memories (CAM""s). Just like other memory devices, a CAM is arranged as an array of memory cells, each cell being capable of storing an electric charge. These charges can be manipulated to store and recall data through the use of special control circuitry in the memory. Each memory cell can store one of two values, depending on whether or not the cell holds a charge. The values 1 and 0 are typically used to represent the charged and uncharged states, respectively, although the reverse may be true. Because the cells can hold either of two possible values (i.e., a 1 or a 0), the cell data values are known as binary digits, or xe2x80x9cbits.xe2x80x9d
In addition to a mechanism for storing data, content addressable memories cells each include a comparison circuit having a xe2x80x9ccomparexe2x80x9d input signal and a xe2x80x9cmatchxe2x80x9d output signal. Typically, a group of cells share the same compare signal, while each cell outputs its own match signal. When a binary value (i.e., a 1 or 0) drives the compare input, each memory cell having the same value as the compare input activates (or xe2x80x9cassertsxe2x80x9d) its match signal. This single-cell matching mechanism is useful for quickly finding data patterns among a plurality of cells in the memory device.
FIG. 1 illustrates a representative CAM 150, comprising an array of memory cells 100-103 and 110-113. As shown in FIG. 1, the cells are organized into 2 rows and 4 columns, although the cells may be organized into any number of rows and columns. Cells 100-103 represent the four columns of row 0, and cells 110-113 represent the four columns of row 1. Each cell includes a storage logic xe2x80x9cSxe2x80x9d and a comparison logic xe2x80x9cC.xe2x80x9d The storage logic S holds the charge that identifies the data value. Each row of cells couples to a xe2x80x9cword linexe2x80x9d signal that activates the storage logic S of each cell for reading and writing data. The cells 100-103 on row 0, for instance, couple to word line WL0, and the cells 110-113 on row 1 couple to word line WL1.
The storage logic of each cell also couples to a xe2x80x9cbit linexe2x80x9d signal, which is shared with other cells in the same column. An inverted bit line also couples to each cell in the same column, carrying a 0 value if the main bit line has a 1 value or a 1 value if the main bit line carries a 0 value. Cells 100 and 110, for example, representing the first column of the array 150, couple to main bit line BL0 and to inverted bit line BL0xe2x80x2. Similarly the cells 101 and 111 in the second column couple to bit lines BL1 and BL1xe2x80x2, the cells 102 and 112 in the third column couple to bit line BL2 and BL2xe2x80x2, and the cells 103 and 113 in the final column couple to bit lines BL3 and BL3xe2x80x2. To read data from a particular cell, the word line coupled to that cell is asserted, causing that cell to dump data from the storage logic S onto the bit lines. To write a data value into a particular cell, the data value is placed onto the bit lines coupled to the cell. Activating the cell""s word line then causes the cell to store the data value from the bit lines into the storage logic S.
The comparison logic C of each cell couples to the cell""s storage logic S and to a pair of compare signals. Each column of cells shares a common pair of compare signals, including a main compare line and an inverted compare line. Cells 100 and 110, for example, couple to main compare line CL0 and inverted compare line CL0xe2x80x2, and cells 101 and 111 share the main compare line CL1 and the inverted compare line CL1xe2x80x2. Similarly, the storage logic of cells 102 and 112 receive main compare line CL2 and inverted compare line CL2xe2x80x2, while cells 103 and 113 receive main compare line CL3 and inverted compare line CL3xe2x80x2. In each cell, the comparison logic C generates a match signal based on the value stored in the cell and on the value of the compare signals. As illustrated in FIG. 1, the match signals on row 0 are ML00 (cell 100), ML01 (cell 101), ML02 (cell 102), and ML03 (cell 103). Similarly, the match signals on row 1 are ML10 (cell 110), ML11 (cell 111), ML12 (cell 112), and ML13 (cell 113). The architecture of CAM 150 is known as a dual port configuration, since the main bit lines are separate from the main compare lines. In a type of configuration known as single port, one signal line functions as both the main bit line and the main compare line, and another signal line functions as the inverted bit line and inverted compare line for each cell.
Memory cells usually are accessed in groups called xe2x80x9cwords.xe2x80x9d Memory words comprise at least two contiguous cells on the same row and share a common word line. For each word, an AND gate 125 may couple together match lines belonging to the cells in that word, to form a unified representation of the match line values. The memory array 150 in FIG. 1, for instance, is constructed using four-bit words, including a first word consisting of the cells 100-103 on row 0, and a second word consisting of the cells 110-113 on row 1. An AND gate 125A receives the match lines ML00, ML01, ML02, and ML03 belonging to cells 100-103. Similarly, an AND gate 125B receives the match lines ML10, ML11, ML12, and ML13 belonging to cells 110-113. Each AND gate 125 generates a word match signal that is asserted if each of the received match lines is asserted. AND gate 125A, for example, asserts the word match 0 signal if each of the match signals ML00, ML01, ML02, and ML03 is asserted, and the AND gate 125B asserts the word match 1 signal if each of the match lines ML10, ML11, ML12, and ML13 is asserted.
Using the compare and match lines, the CAM array 150 is capable of indicating which data words contain a certain pattern. First, the CAM 150 receives the data pattern through the compare lines. The compare lines carry the pattern to be matched, and the inverted compare lines carry the complement of the pattern to be matched. If the value of a cell matches the value on the associated main compare line, then that cell asserts its match line. If the value of a cell matches the value on the inverted compare line, however, then that cell deasserts its match line. If all of the match lines in the same word are asserted, indicating that the pattern exactly matches the sequence of bits in the data word, then the AND gate belonging to that word asserts the match word signal. An encoder or other circuit may be used to generate a code, based on which word match signals are asserted, that identifies the locations (or xe2x80x9caddressesxe2x80x9d) of those words in the memory. Thus, any pattern in the memory array can be quickly located by driving the compare lines with the values in the pattern.
FIG. 2A illustrates an exemplary dual port CAM cell, including the storage logic and comparison logic. The storage logic comprises a pair of cross coupled inverters 200 and 204 and two pass transistors 208 and 212. The output terminal of inverter 200 represents the cell value D, and the output terminal of inverter 204 represents the inverse of the cell value, Dxe2x80x2. The gates of the pass transistors 208 and 212 couple to the word line (WL), so that the pass transistors 208 and 212 become activated when the word line is asserted. The source and drain terminals of the Act pass transistor 208 couple the main bit line (BL) to the input terminal of inverter 204 and to the output terminal of inverter 200. Similarly, the source and drain terminals of the pass transistor 212 couple the inverted bit line (BLxe2x80x2) to the input terminal of inverter 200 and to the output terminal of inverter 204. If the cell is activated by asserting the word line, then the pass transistors 208 and 212 turn on. If complementary data values are driven onto the bit lines from hi the external memory control circuitry (not shown), then the inverters 200 and 204 will store the bit line values, implementing a memory write operation. If the control circuitry drives the main bit line B with a 1 value, for example, and drives the inverted bit line BLxe2x80x2 a 0 value, then inverter 200 will settle into a logic 1 state. If the main bit line B is driven with a 0 value, however, and the inverted bit line BLxe2x80x2 is driven with a 1 value, then inverter 200 will settle into a logic 0 state. If the control circuitry does not drive the bit lines when the pass transistors 208 and 212 are activated, then inverter 200 drives the main bit line B with the cell data value D, and inverter 204 drives the inverted bit line BLxe2x80x2 with the inverted cell value Dxe2x80x2, corresponding to a memory read operation.
The comparison logic comprises a match detect transistor 224 and a pair of pass transistors 216 and 220 which are coupled to the storage logic. Specifically, inverter 204 drives the gate terminal of pass transistor 216, and inverter 200 drives the gate terminal of pass transistor 220. The source and drain terminals of pass transistor 216 couple the main compare line CL to the gate of match transistor 224, and the source and drain terminals of transistor 220 couple the inverted compare line CLxe2x80x2 to the gate of the match transistor 224. The source and drain terminals of the match transistor 224 couple circuit ground to the match line ML. If inverter 200 holds a logic 1 value, then the gate terminal of transistor 220 is activated, coupling the gate terminal of the match transistor 224 to the inverted compare line CLxe2x80x2. If inverter 204 lf holds a logic 1 value, however, then the gate terminal of transistor 216 is activated, coupling the gate terminal of the match transistor to the main compare line CL.
To compare a CAM cell to a particular bit value, the memory control circuitry charges the match line ML to a logic 1 value. Next, the control circuitry drives the bit value onto the compare line CL and the complement of the bit onto the inverted compare line CLxe2x80x2. If the cells holds a logic 1 value, represented by the state of inverter 200, then the logic 0 value of inverter 204 will cut off pass transistor 216, and pass transistor 220 will be turned on, coupling the gate terminal match transistor 224 to the inverted compare line CLxe2x80x2. If the value of the inverted compare line CLxe2x80x2 is logic 0, then the match transistor 224 cuts off, maintaining the match line at its precharged value of logic 1. If the value of the inverted compare line CLxe2x80x2 is logic 1, however, then the match transistor 224 turns on, coupling the match line to ground. The comparison logic functions similarly if the cell holds a logic 0 value on the output terminal of inverter 200. If the inverter 200 holds a logic 0, then inverter 204 turns on pass transistor 216, coupling the gate terminal of match transistor 224 to the main compare line CL, and pass transistor 220 turns off. If the main compare line CL is driven with a logic 1 value, then the match transistor 224 turns on, coupling the match line to ground. If the main compare line holds a logic 0, however, then the match transistor 224 turns off, and the match line maintains its precharged value of logic 1.
FIG. 2B illustrates an exemplary single port CAM cell. The architecture of the single port CAM resembles that of the dual port CAM, except that the main bit line and main compare line share the same signal trace, and the inverted bit line and inverted compare line share the same signal trace. Accordingly, a single port CAM cannot handle compare operations at the same time as read or write cycles, as can a dual port CAM.
Manufacturing defects often cause the faults in the comparison logic. Cells faults can occur in either the storage logic or the comparison logic. Storage logic faults generally include unlinked faults, linked faults, neighborhood pattern sensitive faults, and complex coupling faults. Unlinked faults represent faults that occur in specific cells, without regard to the values of nearby cells. Types of unlinked faults include stuck-at faults, in which a cell holds a particular data value permanently; stuck-open faults, in which a cell is inaccessible; transition faults, in which a cell cannot make a transition between two values; data retention faults, in which a cell fails to retain the correct logic value after a period of time; and coupling faults, in which the value of one cells affects the value of another cell. Table I summarizes unlinked faults.
Coupling faults include inversion faults, in which inverting the value of a first cell inverts the value of a second cell; idempotent faults, in which inverting the value of a first cell causes a particular value (either a 1 or a 0) to be stored in a second cell; bridging faults, in which two cells are shorted together; state faults, in which a first cell is forced to a certain value if and only if a second cell holds a particular value; and disturbance faults, in which a first cell changes value in response to a read or write operation in a second cell. Bridging faults can be one of two types: the AND-type or the OR-type. In an AND-type fault, a first cell is forced to 0 if and only if a 0 is stored in second cell. In an OR-type fault, a first cell is forced to 1 if and only if a 1 is stored in a second cell. Table II summarizes coupling faults.
Other cell faults include linked faults, neighborhood pattern sensitive faults, and complex coupling faults. Linked faults comprise multiple coupling faults which occur when three or more cells interact to form faults. A first cell, for example, may affect the value of a second cell, which affects the value of a third cell. In another linked fault scenario, the first and third cells both affect the value of the second cell. The other previously discussed cell faults, by contrast, each occur between a single pair of cells. Neighborhood pattern sensitive faults typically appear as stuck-at, transition, or two-cell coupling faults, but only occur when nearby cells are in a particular state. Complex coupling are weak coupling faults that tend to occur only when multiple ports access the memory simultaneously. Table III summarizes these other cell faults.
To access memory cells, an address value corresponding to the desired cells must be provided to the control circuitry of the memory device 150. In response, the control circuitry activates the desired cells by asserting the word lines that correspond to the received addresses. Addressing faults occur when no cell is accessed for a given address, multiple cells are accessed simultaneously for a single address, when a cell is not accessible, and when a cell is activated for multiple addresses. Read/write faults either prevent read and/or write operations or permanently set the memory device to read or write. Addressing faults typically stem from defects in the control circuitry, while read/write faults can be caused by defects in the control circuitry or in the individual cells.
A fault in the comparison logic either prevents the cell from identifying a match or causes the cell to assert the match line when no match exists. In some cases, the match line ML is stuck at logic high, so that a comparison operation always results in a bit match. Alternatively, the match line ML is stuck at logic low, so that a comparison operation always results in a bit mismatch. Other types of faults affect the match line ML, depending on the data value stored in the cell during the compare operation. Comparison faults typically appear as stuck-at faults on the compare lines, stuck-at faults on the match line, stuck-on faults at the match transistor 224, stuck-open faults at the match transistor 224, stuck-on faults at the compare pass transistors 216 and 220, or stuck-open faults at the compare pass transistors 216 and 220.
Stuck-at faults on the compare lines occur when the main compare line CL or the inverted compare line CLxe2x80x2 holds a fixed value, either logic 1 or logic 0, which the memory control logic cannot change. As a result, the match line ML becomes stuck at a particular value, either 1 or 0, depending on the cell value. Referring to FIG. 2A, if the cell value is logic 1, then pass transistor 220 is activated. With pass transistor 220 activated, the match line ML is stuck at 1 if the inverted compare line CLxe2x80x2 is stuck at 0, or the match line ML is stuck at 0 if the inverted compare line CLxe2x80x2 is stuck at 1. Similarly, if the cell value is logic 0, then pass transistor 216 is activated. With pass transistor 216 activated, the match line ML is stuck at 0 1 if the main compare line CL is stuck at 0, or the match line ML is stuck at 0 if the main compare line CL is stuck at 1. Other types of stuck-at faults may occur on the match line 224 as well, such as when the source and drain terminals of the match transistor 224 become permanently shorted, coupling the match line ML to ground. Stuck-open faults on the match transistor 224 also occur when the source and drain terminals become permanently open, thus holding the match line ML at the precharged value of logic 1 value during every compare operation.
Stuck-on faults at pass transistor 216 occur when the source and drain terminals are shorted, permanently coupling the gate of transistor 224 to the main compare line CL. Similarly, stuck-on faults at pass transistor 220 occur when the source and drain terminals are shorted, permanently coupling the gate of transistor 224 to the inverted compare line CLxe2x80x2. Stuck-open faults at pass transistors 216 and 220 occur due to permanent open circuits between the source and drain terminals. Thus, a stuck-open fault at pass transistor 216 prevents coupling between the gate of match transistor 224 and the main compare line CL. Similarly, a stuck-open fault at pass transistor 220 will prevent coupling between the gate of match transistor 224 and the inverted compare line CLxe2x80x2. Stuck-on faults at pass transistor 216 and stuck-open faults at pass transistor 220 can only be detected when the cell stores a logic 1. On the other hand, stuck-open faults at pass transistor 216 and stuck-open faults at pass transistor 220 can only be detected when the cell stores a logic 0. Table IV summarizes the comparison faults.
Other faults occur when word lines are shorted to match lines or when bit lines are shorted to compare lines (in a dual port memory). In a typical CAM, word lines and match lines typically run in parallel lines on a common layer of semiconductor. Similarly, bit lines usually are routed in parallel with compare lines, and both coexist on the same layer of semiconductor. Parallel traces in close proximity on the same semiconductor layer are more likely to affect each other, because the lines may become shorted or capacitively coupled. Capacitive coupling is an electromagnetic phenomenon that causes signal lines to react as if the lines were short circuited, even if the lines are not physically connected. If a word line is shorted to a match line, then the state of the word line affects the value of the match line (and vice versa), especially when a comparison operations occurs at the same time as a read/write operation. As a result, the match line may incorrectly identify a data match or may fail to properly identify a data match. In some cases, a short between the match line and word line may prevent activation of the word line. A short between a bit line and a compare line may cause the wrong value to be written to or read from the cell, if a compare operation occurs at the same time as a read or write operation.
Another type of storage/comparison fault occurs when the gate terminal of one of the pass transistors 216 and 220 becomes shorted to the drain terminal of the same transistor. A short between the gate and drain terminals causes the gate terminal to mirror any voltage value applied to the drain terminal (and vice versa). If the drain terminal is attached to the compare line, a gate-to-drain short during a comparison operation causes the transistor to transfer the compare value into the storage logic, potentially changing the stored value.
Memory faults of any kind are unacceptable, so memory devices are thoroughly tested during manufacturing and discarded if any faults are detected. A number of procedures exist for testing memory arrays. Memories typically are tested using a technique called the March C algorithm, for example, or a variant of March C such as the March Cxe2x88x92, March C+, Smarch, or March LR algorithm.
The March C Algorithm includes six xe2x80x9cpasses,xe2x80x9d each of which addresses each memory cell individually. During Pass 1, March C writes a test pattern into the cells. The test pattern may be any desired sequence of bits, such as a xe2x80x9ccheckerboardxe2x80x9d pattern, but often comprises all 0""s. The 0 values can be written in any order, although the cells usually are addressed consecutively from address 0 to address Nxe2x88x921 or from address Nxe2x88x921 to address 0, where N represents the number of bits in the memory. Note that the memory also could be addressed one word at a time, in which case N would represent the number of memory words. Passes 2-5 also address each cell consecutively, executing two operations in sequence at each address. Passes 2 and 3 address the memory from address 0 to address Nxe2x88x921. During the first operation at each address in Pass 2, the test reads the current address to verify the value that was written during Pass 1. If the read operation does not return the value that was written during Pass 1, then a fault is detected. The fault may have occurred either during the write operation of Pass 1 or the read operation of Pass 2 (or both). Next, the test inverts (or xe2x80x9ccomplementsxe2x80x9d) the data value of the current address. Thus, if the current cell holds a 0 value, then the test writes a 1 value to the cell, and vice versa. Similarly, the first operation of Pass 3 performs a read operation to verify the value written in Pass 2, and the second operation writes the inverted value to the cell. If the read operation returns a value different that the one written in Pass 2, then a fault is detected.
Passes 4-5 address the memory from cell Nxe2x88x921 to cell 0. The first operation in Pass 4 reads the current cell to verify the value that was written during Pass 3, and the second operation inverts the value through a write operation. Similarly, each iteration of Pass 5 first reads the value of the current cell to verify the value that was written during Pass 4 and then writes a complemented value to the cell. If the wrong value is read during any iteration of Pass 4 or Pass 5, then a fault is detected. Such a fault may have occurred during the read operation itself or during the previous write operation (or both). During Pass 6, the test reads each cell to verify the value that was written during Pass 5. As in Pass 1, the cells may be addressed in any order but preferably are accessed from address 0 to address Nxe2x88x921 or from address Nxe2x88x921 to address 0. If the wrong value is detected in any cell during Pass 6, a fault is detected. Table V summarizes the operations of the March C Algorithm in which the initial test pattern is zero for each cell.
Unfortunately, the March C algorithm cannot detect faults which occur in the comparison logic of CAM arrays. In recent years, different techniques have been proposed for modeling and testing CAM arrays. Many of these more recent techniques, however, test only the comparison logic, neglecting the storage logic. Other recent techniques test both the comparison logic and the storage logic, but require a much lengthier and complicated test sequence than previous tests. At least one test, for example, requires as many as 24NL operations, where N represents the number of memory words and L represent the number of bits per word. The March C Algorithm, by comparison, requires only 10N operations.
For the foregoing reasons, an efficient and reliable technique for detecting faults in content addressable memory would greatly improve memory testing. Such a technique, if devised, should cover both storage logic faults and comparison logic faults, without requiring an excessive number of operations. Despite the apparent advantages that such a technique would provide, no device or method to date provides these features.
Accordingly, the present invention discloses a CAM testing procedure capable of detecting storage logic faults, comparison logic faults, and faults caused by interactions between the storage and comparison logic. In particular, tests are disclosed for both single port and dual port CAM""s. To uncover faults in the storage logic, a series of read and write operations are performed on each memory word. The read and write operations may conform to a standard test sequence, such as the March C algorithm, or may comprise any other desired test sequence. The CAM test, however, intermixes comparison operations with the read and write operations to uncover faults in the comparison logic as well as in the storage logic.
For dual port memories, the test sequence comprises executing comparison operations in parallel with the read and/or write operations, thus revealing faults between the storage and comparison logic. A comparison operation preferably occurs concurrently with each read operation, except possibly during the final test pass, meaning that at least part of the compare operation overlaps with at least part of the read operation. During one pass, the comparison operation compares each memory word to the expected bit values in the word. If the word match line is deasserted, indicating a mismatch, then a fault is detected. During another pass, the comparison operation tests each word for the complement of the bit values in the word, in order to ensure that the memory is capable of detecting mismatches. If the cell comparison logic improperly asserts the match line, then a fault is detected. The concurrent operations thus detect faults between the storage and comparison logic by activating the storage and comparison logic at the same time. The concurrent operations also detect comparison faults, including stuck-at faults in the compare lines and match lines, as well as stuck-on and stuck-open faults in the comparison transistors.
For single port memories, the test sequence comprises performing a comparison operation following the read/write operations at each address, immediately verifying the comparison logic at each address. During certain test passes, comparison operation either evaluates the word for a match or for a mismatch. If the match line is asserted during a mismatch operation or deasserted during a match operation, then a fault is uncovered. Note that any single port test operation may be performed on a dual port memory. Following each read/write operation with a comparison operation uncovers comparison faults, including stuck-at faults in the compare lines and match lines, as well as stuck-on and stuck-open faults in the comparison transistors.
For both single port and dual port memory tests, the test introduces a set of xe2x80x9cwalkingxe2x80x9d passes which verify that individual cells can properly identify data mismatches. Each walking pass performs a set of comparison operations, preferably without concurrent read or write operations, each of which simultaneously compares all memory address simultaneously with a special compare word. During a first pass of the walking comparison, each memory cell contains a logic 1 value, and the compare word includes at least one logic 0 bit. In a preferred embodiment, the remaining bits in the compare word are logic 1 values. Accordingly, each cell which is compared with the logic 0 bit deasserts its match signal, causing the associated word match signal to deassert. If any word match signal becomes asserted, indicating that the word improperly matched its contents to the compare value, then a fault is detected. During each operation of the walking pass, the logic 0 value is located in a different bit of the compare word.
Similarly, a second pass of the walking comparison utilizes a test word consisting of a logic 1 value in one bit, with logic 0 values in the rest of the test word. Prior to the second walking pass, the test initializes each cell of the memory to logic 0, so that the logic 1 bit in the test word triggers a mismatch in every cell. Thus, if any cell indicates a match between the cell data and the test word, a fault is detected. The logic 1 bit is then xe2x80x9cwalkedxe2x80x9d to each bit location in the test word, executing a comparison operation for each bit position. The walking tests uncover comparison faults on a cell-by-cell basis and verify that the match lines in each cell are properly combined to produce the word match signal.
The dual port test, also known as the xe2x80x9cconcurrent detection test,xe2x80x9d comprises eight test passes. Passes 1, 2, 4, and 6-8 address each memory word separately. At each memory address, either a write operation, a read operation, or both a read operation and a write operation are performed. Pass 1 preferably performs only a write operation at each address, while Pass 8 performs only a read operation at each address. Passes 2, 4, 6, and 7 preferably perform a read operation, followed by a write operation, at each address. During passes 2, 4, 6, and 7, the test further executes comparison operations concurrently with the read operations. During passes 2 and 4, the comparison test words comprise the same values as the data stored in the memory cells. During passes 6 and 7, the comparison test words comprise the complements of the data values stored in the memory cells. Further, passes 2 and 4 preferably access the data words sequentially from the lowest address to the highest address, while passes 6 and 7 preferably access the words sequentially from the highest address to the lowest address. Passes 3 and 5 implement the walking comparison passes.
The single port test, also known as the nonconcurrent detection test, also comprises eight passes. Passes 1, 3, 5, and 8 of the nonconcurrent test comprise substantially the same operations as Passes 1, 3, 5, and 8 of the concurrent detection test. Passes 2, 4, 6, and 7 of the nonconcurrent test also comprise substantially the same operations as Passes 2, 4, 6, and 7 of the concurrent test, but without the concurrent comparison operations. Passes 2 and 4 preferably omit the comparison operations, while Passes 6 and 7 preferably implement the comparison operations following the read and write operations at each address.
Thus, the present invention comprises a combination of features and advantages that enable it to substantially advance the art by providing both single and dual port CAM testing procedures that cover not only storage faults, but also comparison faults and combination storage/comparison faults. These and various other characteristics and advantages of the present invention will be readily apparent to those skilled in the art upon reading the following detailed description of the preferred embodiments of the invention and by referring to the accompanying drawings.